home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Sample.bin / TicTacToe.java < prev    next >
Text File  |  1998-09-15  |  8KB  |  328 lines

  1. /*
  2.  * @(#)TicTacToe.java    1.5 97/02/05
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
  7.  * modify and redistribute this software in source and binary code form,
  8.  * provided that i) this copyright notice and license appear on all copies of
  9.  * the software; and ii) Licensee does not utilize the software in a manner
  10.  * which is disparaging to Sun.
  11.  *
  12.  * This software is provided "AS IS," without a warranty of any kind. ALL
  13.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  14.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  15.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  16.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  17.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  18.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  19.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  20.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  21.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  22.  * POSSIBILITY OF SUCH DAMAGES.
  23.  *
  24.  * This software is not designed or intended for use in on-line control of
  25.  * aircraft, air traffic, aircraft navigation or aircraft communications; or in
  26.  * the design, construction, operation or maintenance of any nuclear
  27.  * facility. Licensee represents and warrants that it will not use or
  28.  * redistribute the Software for such purposes.
  29.  */
  30.  
  31. import java.awt.*;
  32. import java.awt.event.*;
  33. import java.awt.image.*;
  34. import java.net.*;
  35. import java.applet.*;
  36.  
  37. /**
  38.  * A TicTacToe applet. A very simple, and mostly brain-dead
  39.  * implementation of your favorite game! <p>
  40.  *
  41.  * In this game a position is represented by a white and black
  42.  * bitmask. A bit is set if a position is ocupied. There are
  43.  * 9 squares so there are 1<<9 possible positions for each
  44.  * side. An array of 1<<9 booleans is created, it marks
  45.  * all the winning positions.
  46.  *
  47.  * @version     1.2, 13 Oct 1995
  48.  * @author Arthur van Hoff
  49.  * @modified 04/23/96 Jim Hagen : winning sounds
  50.  * @modified 02/10/98 Mike McCloskey : added destroy()
  51.  */
  52. public
  53. class TicTacToe extends Applet implements MouseListener {
  54.     /**
  55.      * White's current position. The computer is white.
  56.      */
  57.     int white;
  58.  
  59.     /**
  60.      * Black's current position. The user is black.
  61.      */
  62.     int black;
  63.  
  64.     /**
  65.      * The squares in order of importance...
  66.      */
  67.     final static int moves[] = {4, 0, 2, 6, 8, 1, 3, 5, 7};
  68.  
  69.     /**
  70.      * The winning positions.
  71.      */
  72.     static boolean won[] = new boolean[1 << 9];
  73.     static final int DONE = (1 << 9) - 1;
  74.     static final int OK = 0;
  75.     static final int WIN = 1;
  76.     static final int LOSE = 2;
  77.     static final int STALEMATE = 3;
  78.  
  79.     /**
  80.      * Mark all positions with these bits set as winning.
  81.      */
  82.     static void isWon(int pos) {
  83.     for (int i = 0 ; i < DONE ; i++) {
  84.         if ((i & pos) == pos) {
  85.         won[i] = true;
  86.         }
  87.     }
  88.     }
  89.  
  90.     /**
  91.      * Initialize all winning positions.
  92.      */
  93.     static {
  94.     isWon((1 << 0) | (1 << 1) | (1 << 2));
  95.     isWon((1 << 3) | (1 << 4) | (1 << 5));
  96.     isWon((1 << 6) | (1 << 7) | (1 << 8));
  97.     isWon((1 << 0) | (1 << 3) | (1 << 6));
  98.     isWon((1 << 1) | (1 << 4) | (1 << 7));
  99.     isWon((1 << 2) | (1 << 5) | (1 << 8));
  100.     isWon((1 << 0) | (1 << 4) | (1 << 8));
  101.     isWon((1 << 2) | (1 << 4) | (1 << 6));
  102.     }
  103.  
  104.     /**
  105.      * Compute the best move for white.
  106.      * @return the square to take
  107.      */
  108.     int bestMove(int white, int black) {
  109.     int bestmove = -1;
  110.     
  111.       loop:
  112.     for (int i = 0 ; i < 9 ; i++) {
  113.         int mw = moves[i];
  114.         if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
  115.         int pw = white | (1 << mw);
  116.         if (won[pw]) {
  117.             // white wins, take it!
  118.             return mw;
  119.         }
  120.         for (int mb = 0 ; mb < 9 ; mb++) {
  121.             if (((pw & (1 << mb)) == 0) && ((black & (1 << mb)) == 0)) {
  122.             int pb = black | (1 << mb);
  123.             if (won[pb]) {
  124.                 // black wins, take another
  125.                 continue loop;
  126.             }
  127.             }
  128.         }
  129.         // Neither white nor black can win in one move, this will do.
  130.         if (bestmove == -1) {
  131.             bestmove = mw;
  132.         }
  133.         }
  134.     }
  135.     if (bestmove != -1) {
  136.         return bestmove;
  137.     }
  138.  
  139.     // No move is totally satisfactory, try the first one that is open
  140.     for (int i = 0 ; i < 9 ; i++) {
  141.         int mw = moves[i];
  142.         if (((white & (1 << mw)) == 0) && ((black & (1 << mw)) == 0)) {
  143.         return mw;
  144.         }
  145.     }
  146.  
  147.     // No more moves
  148.     return -1;
  149.     }
  150.  
  151.     /**
  152.      * User move.
  153.      * @return true if legal
  154.      */
  155.     boolean yourMove(int m) {
  156.     if ((m < 0) || (m > 8)) {
  157.         return false;
  158.     }
  159.     if (((black | white) & (1 << m)) != 0) {
  160.         return false;
  161.     }
  162.     black |= 1 << m;
  163.     return true;
  164.     }
  165.  
  166.     /**
  167.      * Computer move.
  168.      * @return true if legal
  169.      */
  170.     boolean myMove() {
  171.     if ((black | white) == DONE) {
  172.         return false;
  173.     }
  174.     int best = bestMove(white, black);
  175.     white |= 1 << best;
  176.     return true;
  177.     }
  178.  
  179.     /**
  180.      * Figure what the status of the game is.
  181.      */
  182.     int status() {
  183.     if (won[white]) {
  184.         return WIN;
  185.     }
  186.     if (won[black]) {
  187.         return LOSE;
  188.     }
  189.     if ((black | white) == DONE) {
  190.         return STALEMATE;
  191.     }
  192.     return OK;
  193.     }
  194.  
  195.     /**
  196.      * Who goes first in the next game?
  197.      */
  198.     boolean first = true;
  199.  
  200.     /**
  201.      * The image for white.
  202.      */
  203.     Image notImage;
  204.  
  205.     /**
  206.      * The image for black.
  207.      */
  208.     Image crossImage;
  209.  
  210.     /**
  211.      * Initialize the applet. Resize and load images.
  212.      */
  213.     public void init() {
  214.     notImage = getImage(getCodeBase(), "images/not.gif");
  215.     crossImage = getImage(getCodeBase(), "images/cross.gif");
  216.  
  217.     addMouseListener(this);
  218.     }
  219.  
  220.     public void destroy() {
  221.         removeMouseListener(this);
  222.     }
  223.  
  224.     /**
  225.      * Paint it.
  226.      */
  227.     public void paint(Graphics g) {
  228.     Dimension d = getSize();
  229.     g.setColor(Color.black);
  230.     int xoff = d.width / 3;
  231.     int yoff = d.height / 3;
  232.     g.drawLine(xoff, 0, xoff, d.height);
  233.     g.drawLine(2*xoff, 0, 2*xoff, d.height);
  234.     g.drawLine(0, yoff, d.width, yoff);
  235.     g.drawLine(0, 2*yoff, d.width, 2*yoff);
  236.  
  237.     int i = 0;
  238.     for (int r = 0 ; r < 3 ; r++) {
  239.         for (int c = 0 ; c < 3 ; c++, i++) {
  240.         if ((white & (1 << i)) != 0) {
  241.             g.drawImage(notImage, c*xoff + 1, r*yoff + 1, this);
  242.         } else if ((black & (1 << i)) != 0) {
  243.             g.drawImage(crossImage, c*xoff + 1, r*yoff + 1, this);
  244.         }
  245.         }
  246.     }
  247.     }
  248.  
  249.     /**
  250.      * The user has clicked in the applet. Figure out where
  251.      * and see if a legal move is possible. If it is a legal
  252.      * move, respond with a legal move (if possible).
  253.      */
  254.     public void mouseReleased(MouseEvent e) {
  255.     int x = e.getX();
  256.     int y = e.getY();
  257.  
  258.     switch (status()) {
  259.       case WIN:
  260.       case LOSE:
  261.       case STALEMATE:
  262.         play(getCodeBase(), "audio/return.au");
  263.         white = black = 0;
  264.         if (first) {
  265.         white |= 1 << (int)(Math.random() * 9);
  266.         }
  267.         first = !first;
  268.         repaint();
  269.         return;
  270.     }
  271.  
  272.     // Figure out the row/column
  273.     Dimension d = getSize();
  274.     int c = (x * 3) / d.width;
  275.     int r = (y * 3) / d.height;
  276.     if (yourMove(c + r * 3)) {
  277.         repaint();
  278.  
  279.         switch (status()) {
  280.           case WIN:
  281.         play(getCodeBase(), "audio/yahoo1.au");
  282.         break;
  283.           case LOSE:
  284.         play(getCodeBase(), "audio/yahoo2.au");
  285.         break;
  286.           case STALEMATE:
  287.         break;
  288.           default:
  289.         if (myMove()) {
  290.             repaint();
  291.             switch (status()) {
  292.               case WIN:
  293.             play(getCodeBase(), "audio/yahoo1.au");
  294.             break;
  295.               case LOSE:
  296.             play(getCodeBase(), "audio/yahoo2.au");
  297.             break;
  298.               case STALEMATE:
  299.             break;
  300.               default:
  301.             play(getCodeBase(), "audio/ding.au");
  302.             }
  303.         } else {
  304.             play(getCodeBase(), "audio/beep.au");
  305.         }
  306.         }
  307.     } else {
  308.         play(getCodeBase(), "audio/beep.au");
  309.     }
  310.     }
  311.  
  312.     public void mousePressed(MouseEvent e) {
  313.     }
  314.  
  315.     public void mouseClicked(MouseEvent e) {
  316.     }
  317.  
  318.     public void mouseEntered(MouseEvent e) {
  319.     }
  320.  
  321.     public void mouseExited(MouseEvent e) {
  322.     }
  323.  
  324.     public String getAppletInfo() {
  325.     return "TicTacToe by Arthur van Hoff";
  326.     }
  327. }
  328.